package modeloCarmenSanDiego;

import java.util.*;
import modeloCarmenSanDiego.persistencia.GuardadorDeArchivos;

public class Caso {

	private Policia policia;
	private Ladron ladron;
	private ObjetoRobado objetoRobado;
	private List<Ciudad> ciudades;
	private Reloj reloj;

	public Caso(Reloj reloj, Policia policia, List<Sospechoso> sospechosos, List<Ciudad> ciudades, List<ObjetoRobado> objetosARobar){
		this.policia = policia;
		this.ciudades = new ArrayList<Ciudad>(ciudades); // crea una copia de las ciudades
		//toma el primer sospechoso y lo convierte en ladron 
		//(para variar despues se puede hacer shuffle)
		Collections.shuffle(sospechosos);
		this.ladron = new Ladron(sospechosos.get(0));
		this.elegirObjetoARobar(objetosARobar);
		this.ciudades = this.mapear(this.ciudades);
		this.ladron.robarObjeto(this.objetoRobado);
		this.reloj = reloj;
		this.policia.setCiudadActual(objetoRobado.getCiudad());
	}

	//Constructor para desserializar
	public Caso(Policia policia, Ladron ladron, ObjetoRobado robado, List<Ciudad> ciudades, Reloj reloj) {
		this.policia = policia;
		this.ladron = ladron;
		this.objetoRobado = robado;
		this.ciudades = ciudades;
		this.asignarDestinosALasCiudades();
		this.reloj = reloj;
		//this.policia.setCiudadActual(objetoRobado.getCiudad());
	}

	public void elegirObjetoARobar(List<ObjetoRobado> objetosARobar){
		Collections.shuffle(this.ciudades); // mezcla las ciudades para variar el mapeo
		this.objetoRobado = objetosARobar.get((new Random()).nextInt(objetosARobar.size()));
		this.objetoRobado.asignarValorAlObjeto(policia.getRango().getValorDeObjeto());
		this.reordenarCiudadesUbicandoPrimeraLaDelObjetoRobado();
	}

	public List<Ciudad> mapear(List<Ciudad> ciudades){
		this.resetearDestinosDeCiudades();
		this.asignarDestinosALasCiudades();
		return ciudades;
	}

	private void resetearDestinosDeCiudades() {
		for(Ciudad ciudadAResetearDestinos : this.ciudades)
			ciudadAResetearDestinos.resetearDestinos();
	}

	//el mapa de viajes queda armado como un arbol binario
	private void asignarDestinosALasCiudades(){
		ciudades.get(0).addDestino(ciudades.get(1));
		ciudades.get(0).addDestino(ciudades.get(2));
		ciudades.get(0).addDestino(ciudades.get(20)); //una que no sea de las ultimas ni una correcta
		for(int i=1; i<((ciudades.size()-1)/2); i++){
			ciudades.get(i).addDestino(ciudades.get(2*i + 1));
			ciudades.get(i).addDestino(ciudades.get(2*i + 2));
			ciudades.get(i).addDestino(ciudades.get((i - 1)/2));
		}
		List<Ciudad> ciudadesRelleno = new ArrayList<Ciudad>();
		ciudadesRelleno.add(ciudades.get(ciudades.size()-1));
		ciudadesRelleno.add(ciudades.get(ciudades.size()-2));
		ciudadesRelleno.add(ciudades.get(ciudades.size()-3));
		ciudadesRelleno.add(ciudades.get(20));
		//todas las ciudades despues del for tendran 3 destinos
		for(Ciudad ciudadActual : ciudades) 
			for(Ciudad ciudadDestinoRelleno : ciudadesRelleno)
				if(ciudadActual.getDestinos().size() < 3)
					ciudadActual.addDestino(ciudadDestinoRelleno);
	}

	private void reordenarCiudadesUbicandoPrimeraLaDelObjetoRobado() {
		Ciudad origen = this.objetoRobado.getCiudad();
		ciudades.remove(origen);
		ciudades.add(0, origen);
	}

	public Ladron getLadron(){
		return this.ladron;
	}

	public ObjetoRobado getObjetoRobado() {
		return this.objetoRobado;
	}

	public void guardarCiudades(String nombrearchivociudadesguardadas) {
		(new GuardadorDeArchivos()).guardarCiudades(ciudades, nombrearchivociudadesguardadas);
	}

	public void guardarCaso(String nombreArchivoCasoGuardado, OrdenDeArresto orden) {
		(new GuardadorDeArchivos()).guardarCaso(policia, ladron, objetoRobado, nombreArchivoCasoGuardado, this.reloj, orden);
	}

	public List<Ciudad> getCiudadesMapeadas(){
		return this.ciudades;
	}

}
